package com.PuzGame.combinenumbers.Activities;


import java.lang.reflect.Type;
import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Vibrator;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.PuzGame.combinenumbers.GeneralSettings;
import com.PuzGame.combinenumbers.Level;
import com.PuzGame.combinenumbers.LevelGenerator;
import com.PuzGame.combinenumbers.R;
import com.PuzGame.combinenumbers.RateThisApp;
import com.PuzGame.combinenumbers.RationalNumber;
import com.PuzGame.combinenumbers.Tools;
import com.PuzGame.combinenumbers.Interfaces.GeneralSettingsObserver;
import com.PuzGame.combinenumbers.Interfaces.IListChange;
import com.PuzGame.combinenumbers.Level.LevelStatus;
import com.PuzGame.combinenumbers.customViews.CountUp;
import com.PuzGame.combinenumbers.customViews.CustomPopupWindow;
import com.PuzGame.combinenumbers.customViews.FlowLayout;
import com.PuzGame.combinenumbers.customViews.RationalView;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class MainActivity extends Activity implements IListChange, GeneralSettingsObserver{

	protected PowerManager.WakeLock mWakeLock;
	
	private Context context = this;
	private int MaxStageNo;
	private int CurrStageNo;
	private int MaxStageNoStored;
	protected Level lvl;
	protected long Score;
	protected long Surrenderings;
	protected long SolvedStages;
	protected long Undos;
	protected long Resets;
	protected long Ops;
	protected FlowLayout fl;
	protected ImageView PlusButton;
	protected ImageView MinusButton;
	protected ImageView MultiplyButton;
	protected ImageView DivideButton;
	protected TextView LevelNoTV;
	protected TextView GoalTV;
	protected ImageView UndoButton;
	protected ImageView ClearButton ;
	private ImageView ImageViewRight;
	private ImageView ImageViewLeft;
	protected ImageView  ImageViewMarkerRight;
	protected ImageView  ImageViewMarkerLeft;
	protected LinearLayout  ImageViewMarkerCircle;
	protected Menu menu;
	private MenuItem SurrenderMenuItem;
	private MenuItem SolutionMenuItem;	
	protected PopupWindow spw;
	private PopupWindow solpw;
	ArrayList<Integer> MarkerRightResources;
	ArrayList<Integer> MarkerLeftResources;
	ArrayList<Integer> MarkerCircleResources;
	protected TextView ScoreTV;
	private Vibrator vibrator;
	private MediaPlayer mp;
	
	protected GeneralSettings generalSettings;
	
	protected InterstitialAd interstitial;
	private CountUp stopper;

	public void StoreMaxLevel() {
		Gson gson = new Gson();

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

		//Save Value

		StoreCurretLevelStageNo();

		editor.putInt("MaxLvl_Stage", lvl.getStage());

		editor.putLong("MaxLvl_Goal", lvl.getGoal());

		String jsonListOfNumbers = gson.toJson(lvl.getListOfNumbers());
		editor.putString("MaxLvl_ListOfNumbers", jsonListOfNumbers);
		editor.putString("MaxLvl_Solution", lvl.getSolution());

		editor.commit();
		StoreMaxLevelMilis();
		MaxStageNoStored = MaxStageNo;
	}
	
	public void StoreMaxLevelMilis() {
		
		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

	
		editor.putLong("MaxLvl_Milis", GetStopperTime());

		editor.commit();
	}

	
	
	public void StoreCurrLevelMilis() {
	
		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

	
		editor.putLong("CurLvl_Milis", GetStopperTime());

		editor.commit();

	}
	
	
	

	public void StoreCurLevel() {
		Gson gson = new Gson();

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

		//Save Value

		StoreCurretLevelStageNo();

		editor.putInt("CurLvl_Stage", lvl.getStage());

		editor.putLong("CurLvl_Goal", lvl.getGoal());

		String jsonListOfNumbers = gson.toJson(lvl.getListOfNumbers());
		editor.putString("CurLvl_ListOfNumbers", jsonListOfNumbers);
		editor.putString("CurLvl_Solution", lvl.getSolution());

		editor.commit();
		StoreCurrLevelMilis();
	}


	public void StoreCurretLevelStageNo() {

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();
		editor.putInt("CurrStageNo", CurrStageNo);
		editor.commit();

	}



	public void StoreMaxLevelStageNo() {

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();
		editor.putInt("MaxStageNo", MaxStageNo);
		editor.commit();

	}

	public long StoreAdditionalPoints(long pointsToAdd) {

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

		Score = settings.getLong("Score", 0) + pointsToAdd;

		editor.putLong("Score", Score);

		if(pointsToAdd>0)
		{			
			SolvedStages = Math.max(settings.getLong("SolvedStages", 0),MaxStageNo) + 1;

			editor.putLong("SolvedStages", SolvedStages);
		}


		editor.commit();
		
		ScoreTV.setText(String.valueOf(Score));

		return Score;
	}

	public long StoreAdditionalSurrendering() {

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

		Surrenderings = settings.getLong("Surrenderings", 0) + 1;

		editor.putLong("Surrenderings", Surrenderings);
		editor.commit();

		return Surrenderings;
	}
	
	public long StoreAdditionalUndo() {

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

		Undos = settings.getLong("Undos", 0) + 1;

		editor.putLong("Undos", Undos);
		editor.commit();

		return Undos;
	}
	
	public long StoreAdditionalReset() {

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

		Resets = settings.getLong("Resets", 0) + 1;

		editor.putLong("Resets", Resets);
		editor.commit();

		return Resets;
	}
	
	public long StoreAdditionalOp() {

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();

		Ops = settings.getLong("Ops", 0) + 1;

		editor.putLong("Ops", Ops);
		editor.commit();

		return Ops;
	}


	private void RestoreMaxLevel()
	{
		Gson gson = new Gson();
		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);

		int Stage = settings.getInt("MaxLvl_Stage", 0);
		if(Stage != 0)
		{
			long Goal = settings.getLong("MaxLvl_Goal", 0);
			if(Goal != 0)
			{
				String gsonNumbers = settings.getString("MaxLvl_ListOfNumbers", "");
				if(!gsonNumbers.equals(""))
				{
					Type listOfTestObject = new TypeToken<ArrayList<Long>>(){}.getType();
					ArrayList<Long> ListOfNumbers = gson.fromJson(gsonNumbers, listOfTestObject);
					if(ListOfNumbers != null && ListOfNumbers.size()!=0)
					{
						SetExistingLevel(Stage, Goal, ListOfNumbers,settings.getString("MaxLvl_Solution", ""));
						return;
					}
				}
			}
		}


		SetNewLevel(CurrStageNo,false);

	}
	
	private long RestoreMaxLevelMilis()
	{
		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);

		return settings.getLong("MaxLvl_Milis", 0);

	}
	
	private long RestoreCurrLevelMilis()
	{
		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);

		return settings.getLong("CurLvl_Milis", 0);

	}
	
	

	private void RestoreCurLevel()
	{
		Gson gson = new Gson();
		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);

		int Stage = settings.getInt("CurLvl_Stage", 0);
		if(Stage != 0)
		{
			long Goal = settings.getLong("CurLvl_Goal", 0);
			if(Goal != 0)
			{
				String gsonNumbers = settings.getString("CurLvl_ListOfNumbers", "");
				if(!gsonNumbers.equals(""))
				{
					Type listOfTestObject = new TypeToken<ArrayList<Long>>(){}.getType();
					ArrayList<Long> ListOfNumbers = gson.fromJson(gsonNumbers, listOfTestObject);
					if(ListOfNumbers != null && ListOfNumbers.size()!=0)
					{
						SetExistingLevel(Stage, Goal, ListOfNumbers,settings.getString("CurLvl_Solution", ""));
						return;
					}
				}
			}
		}


		SetNewLevel(CurrStageNo,false);

	}

	public void displayInterstitial() {
		// If Ads are loaded, show Interstitial else show nothing.
		if (interstitial.isLoaded()) {
			interstitial.show();
		}
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		
		setContentView(GetLayoutId());

		// Prepare the Interstitial Ad
		interstitial = new InterstitialAd(MainActivity.this);
		// Insert the Ad Unit Id
		interstitial.setAdUnitId("ca-app-pub-3312240845147288/8736153852");

		//Locate the Banner Ad in activity_main.xml
		AdView adView = (AdView) this.findViewById(R.id.adView);

		// Request for Ads
		AdRequest adRequest = new AdRequest.Builder()

		// Add a test device to show Test Ads
		//.addTestDevice(AdRequest.DEVICE_Id_EMULATOR)
		//.addTestDevice("D87C1D2DC0F47136998758A395EA7E70")
		.build();

		// Load ads into Banner Ads
		adView.loadAd(adRequest);

		// Load ads into Interstitial Ads
		interstitial.loadAd(adRequest);

		// Prepare an Interstitial Ad Listener
		interstitial.setAdListener(new AdListener() {
			public void onAdLoaded() {
				// Call displayInterstitial() function
				displayInterstitial(); 
			}
		});

		/* This code together with the one in onDestroy() 
         * will make the screen be always on until this Activity gets destroyed. */
        final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
        
		ClearButton = ((ImageView)findViewById(R.id.clearButton));
		UndoButton = ((ImageView)findViewById(R.id.undoButton));
		GoalTV = ((TextView)findViewById(R.id.GoalTV));
		//GoalTV.setTextSize(50);
		LevelNoTV = ((TextView)findViewById(R.id.LevelNoTV));
		PlusButton = ((ImageView)findViewById(R.id.plusButton));
		MinusButton = ((ImageView)findViewById(R.id.minusButton));
		MultiplyButton = ((ImageView)findViewById(R.id.multiplyButton));
		DivideButton = ((ImageView)findViewById(R.id.divideButton));
		fl = (FlowLayout) findViewById(R.id.NumberList);
		
		ImageViewMarkerRight =  ((ImageView)findViewById(R.id.imageViewMarkerRight));
		ImageViewMarkerLeft =  ((ImageView)findViewById(R.id.imageViewMarkerLeft));
		ImageViewMarkerCircle =  ((LinearLayout)findViewById(R.id.llMarkerCircle));
		MarkerRightResources = new ArrayList<Integer>();
		MarkerLeftResources = new ArrayList<Integer>();
		MarkerCircleResources = new ArrayList<Integer>();
		MarkerRightResources.add(R.drawable.marker_right1);
		MarkerRightResources.add(R.drawable.marker_right2);
		
		MarkerLeftResources.add(R.drawable.marker_left1);
		MarkerLeftResources.add(R.drawable.marker_left2);
		
		MarkerCircleResources.add(R.drawable.circle1);
		MarkerCircleResources.add(R.drawable.circle2);
		MarkerCircleResources.add(R.drawable.circle3);
		MarkerCircleResources.add(R.drawable.circle4);
		MarkerCircleResources.add(R.drawable.circle5);
		
		ScoreTV = (TextView) findViewById(R.id.Score);

		
		
		
		ClearButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if(lvl.ResetLevel())
				{
					StoreAdditionalReset();
				}
			}
		});

		UndoButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if(lvl.Undo())
				{
					StoreAdditionalUndo();
				}
			}
		});

		PlusButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				lvl.SetOperation(0);
			}
		});

		MinusButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				lvl.SetOperation(1);
			}
		});

		MultiplyButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				lvl.SetOperation(2);
			}
		});

		DivideButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				lvl.SetOperation(3);
			}
		});
		
		initSpecificsViews();

		
		
		//AppRater.app_launched(this);
	}

	public int GetLayoutId() {
		return R.layout.activity_main;
	}

	public void initSpecificsViews() {
		stopper = (CountUp) findViewById(R.id.stopper);
		ImageViewLeft = ((ImageView)findViewById(R.id.imageViewLeft));
		ImageViewRight = ((ImageView)findViewById(R.id.imageViewRight));	
		ImageViewLeft.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				SetNewLevel(lvl.getStage()-1,false);

			}
		});

		ImageViewLeft.setOnLongClickListener(new OnLongClickListener() {

			@Override
			public boolean onLongClick(View arg0) {
				JumpTo(lvl.getStage()/2);
				return true;
			}
		});


		ImageViewRight.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {


				if(lvl.getStage()+1 > MaxStageNo)
					return;
				if(lvl.getStage()+1 == MaxStageNo && MaxStageNo == MaxStageNoStored)
					RestoreMaxLevel();
				else
					SetNewLevel(lvl.getStage()+1,false);
			}
		});

		ImageViewRight.setOnLongClickListener(new OnLongClickListener() {

			@Override
			public boolean onLongClick(View arg0) {
				JumpTo((lvl.getStage()+MaxStageNo)/2+1);
				return true;
			}
		});
		
		ShowStopper();
	}

	

	@Override
	protected void onStart()
	{
		super.onStart();

		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);

		//Initialize to the default value if first run or restore the saved value
		

		Score = settings.getLong("Score", 0);
		Surrenderings = settings.getLong("Surrenderings", 0);
		Undos = settings.getLong("Undos", 0);
		Resets = settings.getLong("Resets", 0);
		Ops = settings.getLong("Ops", 0);
		SolvedStages = settings.getLong("SolvedStages", 0);
		
		generalSettings = Tools.RestoreGS(context);
		generalSettings.attach(this);

		RateThisApp.onStart(this);
		
		this.findViewById(android.R.id.content).getRootView().post(new Runnable() {
			   public void run() {
				   RateThisApp.showRateDialogIfNeeded(context);
			   }
			});
		
		ScoreTV.setText(String.valueOf(Score));
		
		OnstartSpecifics();      
		
		
		
		
		
	}

	public void OnstartSpecifics() {
		
		SharedPreferences settings = getSharedPreferences("SaveInfo", MODE_PRIVATE);
		MaxStageNo = settings.getInt("MaxStageNo", 1);
		CurrStageNo = settings.getInt("CurrStageNo", 1);
		MaxStageNoStored = settings.getInt("MaxLvl_Stage", 1);
		if(MaxStageNo == CurrStageNo)
		{
			RestoreMaxLevel();
		}
		else
		{
			RestoreCurLevel();
		}
	}
	
	@Override
	protected void onPause()
	{
		if(generalSettings.isKeepAwake() && mWakeLock.isHeld())
			this.mWakeLock.release();
		StopStopper();
        super.onPause();
	}

	
	
	@Override
	protected void onResume()
	{
        super.onResume();
        if(generalSettings.isKeepAwake())
        	this.mWakeLock.acquire();
        StartStopper();
	}

	
	

	public void SetNewLevel(int Stage, boolean ForceToStore) {
		if(Stage<1)
		{
			return;
		}

		StopStopper();
		
		lvl = new Level(Stage, this );
		
		ResetStopper();
		
		if(lvl.getStage()>MaxStageNoStored || ForceToStore)			
		{
			StoreMaxLevel();
		}
		else
		{
			StoreCurLevel();
		}

		GoalTV.setText(Long.toString(lvl.getGoal()));
		
		ImageViewMarkerRight.setBackgroundResource(GetRandomMarkerRightResource());
		ImageViewMarkerLeft.setBackgroundResource(GetRandomMarkerLeftResource());
		ImageViewMarkerCircle.setBackgroundResource(GetRandomMarkerCircleResource());

		
		SetLevelNoText();

		CurrStageNo = lvl.getStage();
		
		


		if(SurrenderMenuItem != null && SolutionMenuItem != null)
		{
			if(CurrStageNo == MaxStageNo  && MaxStageNo != 1)
			{
				SurrenderMenuItem.setVisible(true);
				SolutionMenuItem.setVisible(false);
			}
			else
			{
				SurrenderMenuItem.setVisible(false);
				SolutionMenuItem.setVisible(true);
			}
		}

		StoreCurretLevelStageNo();

		if(ImageViewRight!=null && ImageViewLeft!=null )
		{
			if(CurrStageNo == MaxStageNoStored)
				ImageViewRight.setImageResource(R.drawable.right_empty);
			else
			{
				ImageViewRight.setImageResource(R.drawable.right);
			}
			if(CurrStageNo == 1)
				ImageViewLeft.setImageResource(R.drawable.left_empty);
			else
			{
				ImageViewLeft.setImageResource(R.drawable.left);
			}
		}

	}

	protected int GetRandomMarkerRightResource() {
		return MarkerRightResources.get((int)Math.abs(LevelGenerator.RandomNumber(0, MarkerRightResources.size()-1)));
	}

	protected int GetRandomMarkerLeftResource() {
		return MarkerLeftResources.get((int)Math.abs(LevelGenerator.RandomNumber(0, MarkerLeftResources.size()-1)));
	}

	protected int GetRandomMarkerCircleResource() {
		return MarkerCircleResources.get((int)Math.abs(LevelGenerator.RandomNumber(0, MarkerCircleResources.size()-1)));
	}

	public void SetExistingLevel(int Stage, long goal, ArrayList<Long> listOfNumbers, String sol) {

		lvl = new Level(Stage, goal, listOfNumbers, sol,  this );

		GoalTV.setText(Long.toString(lvl.getGoal()));
		
		ImageViewMarkerRight.setBackgroundResource(GetRandomMarkerRightResource());
		ImageViewMarkerLeft.setBackgroundResource(GetRandomMarkerLeftResource());
		ImageViewMarkerCircle.setBackgroundResource(GetRandomMarkerCircleResource());

		SetLevelNoText();

		CurrStageNo = lvl.getStage();
		
		StartStopper();

		if(SurrenderMenuItem != null && SolutionMenuItem !=null)
		{
			if(CurrStageNo == MaxStageNo  && MaxStageNo != 1)
			{
				SurrenderMenuItem.setVisible(true);
				SolutionMenuItem.setVisible(false);
			}
			else
			{
				SurrenderMenuItem.setVisible(false);
				SolutionMenuItem.setVisible(true);
			}
		}

		StoreCurretLevelStageNo();
		
		if(ImageViewRight!=null && ImageViewLeft!=null )
		{
			if(CurrStageNo == MaxStageNoStored)
				ImageViewRight.setImageResource(R.drawable.right_empty);
			else
			{
				ImageViewRight.setImageResource(R.drawable.right);
			}
			if(CurrStageNo == 1)
				ImageViewLeft.setImageResource(R.drawable.left_empty);
			else
			{
				ImageViewLeft.setImageResource(R.drawable.left);
			}
		}

	}



	public void ResetLevel() {

		lvl.ResetLevel();

		TextView GoalTV = ((TextView)findViewById(R.id.GoalTV));
		GoalTV.setText(Long.toString(lvl.getGoal()));

		SetLevelNoText();
	}
	
	public void SetLevelNoText() {
		LevelNoTV.setText(String.format(getString(R.string.levelNo), lvl.getStage()));
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);

		this.menu = menu;

		MenuItem TempMenuItem = this.menu.findItem(R.id.menu_overflow);
		SurrenderMenuItem = TempMenuItem.getSubMenu().findItem(R.id.surrender);
		SolutionMenuItem = TempMenuItem.getSubMenu().findItem(R.id.solution);
		if(lvl.getStage() == MaxStageNo && MaxStageNo != 1)
		{
			SurrenderMenuItem.setVisible(true);
			SolutionMenuItem.setVisible(false);
		}
		else
		{
			SurrenderMenuItem.setVisible(false);
			SolutionMenuItem.setVisible(true);
		}	
		
		if(RateThisApp.AlreadyRated())
		{
			MenuItem RateMenuItem = TempMenuItem.getSubMenu().findItem(R.id.rate);
			RateMenuItem.setVisible(false);
		}
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.share_level) {

			shareIt();

			return true;
		}
		if (id == R.id.jump_to_level) {


			JumpTo((MaxStageNo/2)+1);

			return true;
		}	

		if (id == R.id.surrender || id == R.id.solution) {

			Surrender();

			return true;
		}	
		
		if (id == R.id.challenge) {

			facebook();

			return true;
		}		

		if (id == R.id.statistics) {

			initiateStatisticsPopupWindow();

			return true;
		}	
		
		if (id == R.id.rate) {

			RateThisApp.RateNow(this);

			return true;
		}	
		
		if (id == R.id.settings) {

			ShowSettings(generalSettings);

			return true;
		}
		
		

		return super.onOptionsItemSelected(item);
	}

	protected void ShowSettings(final GeneralSettings gs) {
		
		SharedPreferences settings = getSharedPreferences("GeneralSettings", MODE_PRIVATE);
		final SharedPreferences.Editor editor = settings.edit();

		
		final CheckBox SFXCB = new CheckBox(context);
		final CheckBox VibrationCB = new CheckBox(context);
		final CheckBox QuickPlayModeCB = new CheckBox(context);
		final CheckBox KeepAwakeCB = new CheckBox(context);
		
		OnCheckedChangeListener listener = new OnCheckedChangeListener() {
			
			
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				if(buttonView.equals(SFXCB))
				{
					editor.putBoolean("SFX", isChecked);
					gs.setSFX(isChecked);
				}
				else if(buttonView.equals(VibrationCB))
				{
					editor.putBoolean("Vibration", isChecked);
					gs.setVibration(isChecked);
				}
				else if(buttonView.equals(QuickPlayModeCB))
				{
					editor.putBoolean("QuickPlayMode", isChecked);
					gs.setQuickPlayMode(isChecked);
				}
				else if(buttonView.equals(KeepAwakeCB))
				{
					editor.putBoolean("KeepAwake", isChecked);
					gs.setKeepAwake(isChecked);
				}
				editor.commit();
				
			}
		};
		
		
		
		VibrationCB.setText(getString(R.string.Vibration));
		VibrationCB.setChecked(gs.isVibration());
		VibrationCB.setOnCheckedChangeListener(listener);

		
		SFXCB.setText(getString(R.string.SFX));
		SFXCB.setChecked(gs.isSFX());
		SFXCB.setOnCheckedChangeListener(listener);
		
		QuickPlayModeCB.setText(getString(R.string.QuickPlayMode));
		QuickPlayModeCB.setChecked(gs.isQuickPlayMode());
		QuickPlayModeCB.setOnCheckedChangeListener(listener);
		
		KeepAwakeCB.setText(getString(R.string.KeepAwake));
		KeepAwakeCB.setChecked(gs.isKeepAwake());
		KeepAwakeCB.setOnCheckedChangeListener(listener);
		
		
		
		CustomPopupWindow cpw = new CustomPopupWindow(context);
		cpw.setCancelable(null).
		setTitle(getString( R.string.settings)).
		AddSpecialView(VibrationCB, null).
		AddSpecialView(SFXCB, null).
		AddSpecialView(QuickPlayModeCB, null).
		AddSpecialView(KeepAwakeCB, null).
		Show();	
		
	}

	protected void shareIt() {
		Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
		sharingIntent.setType("text/plain");

		String numbers="";
		int i = 0;
		for (i = 0; i < lvl.getListOfNumbers().size()-2; i++) {
			numbers+=lvl.getListOfNumbers().get(i)+", ";
		}
		numbers+= lvl.getListOfNumbers().get(i++)+" ";

		String shareBody = String.format(getString(R.string.share_message), lvl.getGoal(), numbers, lvl.getListOfNumbers().get(i));
		String shareSubject = String.format(getString(R.string.share_subject), getString(R.string.app_name), lvl.getStage());

		sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, shareSubject);
		sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
		startActivity(Intent.createChooser(sharingIntent, getString(R.string.share_via)));
	}

	private void JumpTo(int defaultVal) {
		if(defaultVal == 0)
		{
			defaultVal = 1;
		}
		else if(defaultVal>MaxStageNo)
		{
			defaultVal = MaxStageNo;
		}

		final NumberPicker aNumberPicker = new NumberPicker(context);
		aNumberPicker.setMaxValue(MaxStageNo);
		aNumberPicker.setMinValue(1);
		aNumberPicker.setValue(defaultVal);

		RelativeLayout.LayoutParams numPicerParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
		numPicerParams.addRule(RelativeLayout.CENTER_HORIZONTAL);

		CustomPopupWindow cpw = new CustomPopupWindow(this);
		cpw.
		setTitle(getString(R.string.select_level_number)).
		AddSpecialView(aNumberPicker,numPicerParams).
		setPositiveButton(true, getString(R.string.jump), 0, new OnClickListener() {
			@Override
			public void onClick(View v) {
				if(aNumberPicker.getValue() == MaxStageNo && MaxStageNo == MaxStageNoStored)
					RestoreMaxLevel();
				else
					SetNewLevel(aNumberPicker.getValue(),false);

			}
		}).
		setNegativeButton(true, getString(R.string.cancel),0, null).
		setCancelable(null).
		Show();

	}

	private void Surrender() {
		final String sol = lvl.getSolution();
		final long goal = lvl.getGoal();
		
		if(lvl.getStage() == MaxStageNo && lvl.getStage()!=1)
		{
		
			CustomPopupWindow cpw = new CustomPopupWindow(context);
			cpw.
			setTitle(getString(R.string.do_you_give_up)).
			setMessage(String.format(getString(R.string.surrender_message), lvl.getStage(), lvl.getStage()-1)).
			setPositiveButton(true, getString(R.string.i_surrender), 0, new OnClickListener() {
				@Override
				public void onClick(View v) {
					SeeSolutionDialog(sol, goal);
					lvl.setStatus(LevelStatus.DONE_GAVE_UP);
					LevelDown();
				}
			}).
			setNegativeButton(true, getString(R.string.no_way), 0, null).
			setCancelable(null).
			Show();
			
		}
		else
		{
			SeeSolutionDialog(sol, goal);
		}
		
	}
	
	private void challenge()
	{
		Intent intent = new Intent(this, ChallengeActivity.class);
		startActivity(intent);
	}
	
	private void facebook()
	{
		Intent intent = new Intent(this, ChallengesArenaActivity.class);
		startActivity(intent);
	}
	
	public void SeeSolutionDialog(final String sol, final long goal) {
		
		
		CustomPopupWindow cpw = new CustomPopupWindow(context);
		cpw.
		setTitle(getString(R.string.do_you_want_to_see_solution)).
		setMessage(String.format(getString(R.string.solution_message), Score/4, Score )).
		setPositiveButton(true, getString(R.string.yes_please), 0, new OnClickListener() {
			@Override
			public void onClick(View v) {

				StoreAdditionalPoints(-(Math.abs(Score/4)));
				initiateSolutionPopupWindow(sol,goal);	
				if(lvl.getStage() == MaxStageNo)
				{
					
				}
				else
				{
					SetNewLevel(lvl.getStage(), false);
				}
			}
		}).
		setNegativeButton(true, getString(R.string.no_thanks),0,  null).
		setCancelable(null).
		Show();
	}

	private void LevelDown() {
		if(MaxStageNo > 1)
		{
			Surrenderings = StoreAdditionalSurrendering();
			MaxStageNo--;
			StoreMaxLevelStageNo();
			MaxStageNoStored--;
			SetNewLevel(MaxStageNo,true);
		}
	}



	@Override
	public void AddView(RationalView rv) {
		fl.addView(rv);		
	}

	@Override
	public void AddView(int pos, RationalView rv) {
		fl.addView(rv, pos);
	}

	@Override
	public void RemoveView(RationalView rv) {
		fl.removeView(rv);	
	}

	@Override
	public void RemoveLastView() {
		if(fl.getChildCount() == 0)
			return;

		fl.removeViewAt(fl.getChildCount()-1);
	}

	@Override
	public void ClearAll() {
		fl.removeAllViews();
	}

	@Override
	public void SelectOperation(int OP) {

		PlusButton.setImageResource(R.drawable.plus);
		MinusButton.setImageResource(R.drawable.minus);
		MultiplyButton.setImageResource(R.drawable.multiply);
		DivideButton.setImageResource(R.drawable.divide);

		switch (OP) {
		case 0:
			PlusButton.setImageResource(R.drawable.plus_sell);
			break;

		case 1:
			MinusButton.setImageResource(R.drawable.minus_sel);
			break;

		case 2:
			MultiplyButton.setImageResource(R.drawable.multiply_sel);
			break;

		case 3:
			DivideButton.setImageResource(R.drawable.divide_sel);
			break;

		}

	}

	@Override
	public void StageCleared() {
		
		StopStopper();
		
		lvl.setStatus(LevelStatus.DONE_CLEARED);
		
		playSound(R.raw.stage_cleared);
		boolean newRecord = false;
		long AdditionalPoints = (long) Math.pow(lvl.getStage(), 2);
		Score = StoreAdditionalPoints(AdditionalPoints);
		
		if(MaxStageNo == lvl.getStage())
		{
			MaxStageNo++;
			StoreMaxLevelStageNo();
			newRecord = true;
		}

		
		CustomPopupWindow cpw = new CustomPopupWindow(context);
		cpw.
		setTitle(getString(R.string.stage_cleared)).
		setPositiveButton(true, getString(R.string.next_level),0,  new OnClickListener() {
			@Override
			public void onClick(View v) {
				if(lvl.getStage()+1 > MaxStageNo)
					return;
				if(lvl.getStage()+1 == MaxStageNo && MaxStageNo == MaxStageNoStored)
					RestoreMaxLevel();
				else
					SetNewLevel(lvl.getStage()+1,false);

			}
		});
		
		if(!newRecord)
		{
			cpw.setMessage(String.format(getString(R.string.good_job_message) , AdditionalPoints, MaxStageNo));
		}
		else
		{
			cpw.setMessage(String.format(getString(R.string.great_job_message), AdditionalPoints,MaxStageNo));
		}

		if(!newRecord)
		{
			cpw.setNeutral1Button(true, String.format(getString(R.string.to_level_x), MaxStageNo),
					0,
					new OnClickListener() {
				@Override
				public void onClick(View v) {
					RestoreMaxLevel();		
				}
			});
		}
		
		cpw.
		setNeutral2Button(false, "",R.drawable.share, new OnClickListener() {
			@Override
			public void onClick(View v) {
				shareIt();
			}
		}).
		setNeutral3Button(false, "",R.drawable.solution, new OnClickListener() {
			@Override
			public void onClick(View v) {
				initiateSolutionPopupWindow(lvl.getSolution(),lvl.getGoal());
			}
		}).Show();

	}




	protected void initiateStatisticsPopupWindow() {

		LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View layout = inflater.inflate(R.layout.statistics_pop_win,
				(ViewGroup) ((Activity)context).findViewById(R.id.statisticsPopWin));
		WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
		lp.width = WindowManager.LayoutParams.MATCH_PARENT;
		lp.height = WindowManager.LayoutParams.MATCH_PARENT;
		spw = new PopupWindow(layout, lp.width, lp.height, true);
		spw.showAtLocation(layout, Gravity.CENTER_VERTICAL, 0, 0);


		ImageButton btncancel = (ImageButton) layout.findViewById(R.id.button_close);

		LinearLayout statisticsLL = (LinearLayout) layout.findViewById(R.id.statistics_pop_win);

		

		TextView tvTitle = (TextView) layout.findViewById(R.id.Title);

		
		tvTitle.setText(context.getString(R.string.statistics_title));
		
		addStatiscticView(statisticsLL);
		

		btncancel.setOnClickListener(statistics_cancel_click);

	}

	protected void addStatiscticView(LinearLayout statisticsLL) {
		int SizeOfDividers = 15;
		LayoutParams tvlp = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

		TextView tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText(String.format(getString(R.string.stat_score), Score));
		statisticsLL.addView(tv1);

		tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText(String.format(getString(R.string.stat_stages_solved), SolvedStages));
		statisticsLL.addView(tv1);

		tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText(String.format(getString(R.string.stat_surrenderings), Surrenderings));
		statisticsLL.addView(tv1);
		
		tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText(String.format(getString(R.string.stat_undos), Undos));
		statisticsLL.addView(tv1);
		
		tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText(String.format(getString(R.string.stat_resets), Resets));
		statisticsLL.addView(tv1);
		
		tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText(String.format(getString(R.string.stat_ops), Ops));
		statisticsLL.addView(tv1);
	}


	private OnClickListener statistics_cancel_click = new OnClickListener()
	{
		public void onClick(View v) {
			spw.dismiss();

		}
	};
	
	

	void initiateSolutionPopupWindow(String sol, long goal) {

		LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View layout = inflater.inflate(R.layout.solution_pop_win,
				(ViewGroup) ((Activity)context).findViewById(R.id.solutionPopWin));
		WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
		lp.width = WindowManager.LayoutParams.MATCH_PARENT;
		lp.height = WindowManager.LayoutParams.MATCH_PARENT;
		solpw = new PopupWindow(layout, lp.width, lp.height, true);
		solpw.showAtLocation(layout, Gravity.CENTER_VERTICAL, 0, 0);


		ImageButton btncancel = (ImageButton) layout.findViewById(R.id.button_close);

		FlowLayout fl = (FlowLayout) layout.findViewById(R.id.NumberList);

		int SizeOfDividers = 15;

		TextView tvTitle = (TextView) layout.findViewById(R.id.SolutionTiltleTV);
		TextView tvScoreLeft = (TextView) layout.findViewById(R.id.ScoreLeft);

		tvTitle.setText(context.getString(R.string.solution_title));

		LayoutParams tvlp = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
		LayoutParams ivlp = new LayoutParams(SizeOfDividers*5,SizeOfDividers*5);
		TextView tv1 = new TextView(context);
		ImageView ivPlus = null;
		ImageView ivMinus= null;
		ImageView ivMult= null;
		ImageView ivDiv= null;


		String[] data = sol.split("@");
		for (String string : data)
		{
			if(string.equals("+"))
			{
				ivPlus = new ImageView(context);
				ivPlus.setLayoutParams(ivlp);
				ivPlus.setImageResource(R.drawable.plus);


				fl.addView(ivPlus);
			}
			else if(string.equals("-"))
			{

				ivMinus = new ImageView(context);
				ivMinus.setLayoutParams(ivlp);
				ivMinus.setImageResource(R.drawable.minus);


				fl.addView(ivMinus);
			}
			else if(string.equals("X"))
			{

				ivMult = new ImageView(context);
				ivMult.setLayoutParams(ivlp);
				ivMult.setImageResource(R.drawable.multiply);


				fl.addView(ivMult);
			}
			else if(string.equals("/"))
			{

				ivDiv = new ImageView(context);
				ivDiv.setLayoutParams(ivlp);
				ivDiv.setImageResource(R.drawable.divide);


				fl.addView(ivDiv);
			}
			else if(string.equals("(")|| string.equals(")"))
			{
				tv1 = new TextView(context);
				tv1.setLayoutParams(tvlp);
				tv1.setTextSize(SizeOfDividers);
				tv1.setTypeface(null, Typeface.BOLD);	
				tv1.setText(string);
				fl.addView(tv1);
			}
			else 
			{
				RationalNumber rn;
				try  
				{  
					rn = new RationalNumber(Long.parseLong(string), 1); 
				}  
				catch(NumberFormatException nfe)  
				{  
					continue;  
				}

				RationalView rvToAdd = new RationalView(context, rn);
				rvToAdd.setTextSize(SizeOfDividers);
				fl.addView(rvToAdd);
			}
		}
		
		tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText("=");
		fl.addView(tv1);
		
		tv1 = new TextView(context);
		tv1.setLayoutParams(tvlp);
		tv1.setTextSize(SizeOfDividers*2);
		tv1.setTypeface(null, Typeface.BOLD);	
		tv1.setText(String.valueOf(goal));
		fl.addView(tv1);

		
		LinearLayout llFiller = new LinearLayout(context);
		llFiller.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 15));
		fl.addView(llFiller);

		tvScoreLeft.setText(String.format(getString(R.string.surrender_score), Score));

		btncancel.setOnClickListener(solution_cancel_click);

	}


	private OnClickListener solution_cancel_click = new OnClickListener()
	{
		public void onClick(View v) {
			solpw.dismiss();
			OnSolutionCancel();

		}
	};
	
	protected void OnSolutionCancel() {
		
	}

	public static boolean isNumeric(String str)  
	{  
		try  
		{  
			long l = Long.parseLong(str);  
		}  
		catch(NumberFormatException nfe)  
		{  
			return false;  
		}  
		return true;  
	}

	@Override
	public void OpDone() 
	{
		StoreAdditionalOp();
	}

	@Override
	public void StackIsEmpty()
	{
		UndoButton.setImageResource(R.drawable.undo_grey);
		ClearButton.setImageResource(R.drawable.clear_grey);
	}

	@Override
	public void StackHasItems()
	{
		UndoButton.setImageResource(R.drawable.undo);
		ClearButton.setImageResource(R.drawable.clear);
	}
	
	public void StartStopper() {
		if(stopper!= null)
        {
			if(lvl.getStage() == MaxStageNo)
			{
				stopper.setBase(SystemClock.elapsedRealtime()-RestoreMaxLevelMilis());
			}
			else
			{
				stopper.setBase(SystemClock.elapsedRealtime()-RestoreCurrLevelMilis());
			}
        	stopper.start();
        }
	}
	
	public void ResetStopper() {
		if(stopper!= null)
        {
			stopper.setBase(SystemClock.elapsedRealtime());
			
        	stopper.start();
        }
	}
	
	public void ShowStopper() {
		if(stopper != null)
			stopper.setVisibility(View.VISIBLE);
	}
	
	public void StopStopper() {
		if(stopper!= null)
		{
			if(lvl.getStage() == MaxStageNo)
			{
				StoreMaxLevelMilis();
			}
			else
			{
				StoreCurrLevelMilis();
			}
			stopper.stop();
		}
	}
	public long GetStopperTime() {
		if(stopper!= null)
		{
			return SystemClock.elapsedRealtime() - stopper.getBase();
		}
		return 0;
	}

	@Override
	public void onSFXChanged() {
		playSound(R.raw.yoink);
		
	}

	@Override
	public void onVibrationChanged() {
		vibrate(500);
		
	}

	@Override
	public void onQuickPlayModeChanged() {
			
		
	}

	@Override
	public void onKeepAwakeChanged() {
		
		if(!generalSettings.isKeepAwake() && mWakeLock.isHeld())
		{
			mWakeLock.release();
		}
		else if(generalSettings.isKeepAwake() && ! mWakeLock.isHeld())
		{
			mWakeLock.acquire();
		}
		
	}

	@Override
	public boolean getQuickPlayMode() {
		return generalSettings.isQuickPlayMode();
	}

	@Override
	public void vibrate(int i) {
		if(!generalSettings.isVibration())
			return;
		if(vibrator == null)
			vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
		vibrator.vibrate(i);	
	}

	@Override
	public void playSound(int resid) {
		if(!generalSettings.isSFX())
			return;
		if(mp != null)
		{
			if(mp.isPlaying())
			{
				mp.stop();
			}
			mp.release();
		}
		mp = MediaPlayer.create(getApplicationContext(), resid);

		mp.start();
		
	}

}
